﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace OnLineLogFileClient
{
    public class AAFLogTranJobAsync : SocketTcpJobAsync
    {
        public string RootPath { get; set; }
        private string FilePath { get; set; }
        private FileStream fs { get; set; }
        public override void Run()
        {
            var task = Task.Factory.StartNew(() =>
              {
                  try
                  {
                      int i = 0;
                      while (true)
                      {
                          if (!this.HasConnected)
                          {
                              if (!this.TryConnect())
                              {
                                  return;
                              }

                              var up = new UpdateJob();
                              up.Run();
                              up.Dispose();

                          }

                          if (this.CheckFile())
                          {
                              this.TryFileTranRun();
                          }
                          else
                          {
                              this.InvMsg("aaflog_文件检测不到");
                              if (i > 5)
                              {
                                  return;
                              }
                              Thread.Sleep(90000);
                          }
                      }
                  }
                  catch (Exception ex)
                  {
                      LogServices.LogService.Instance.Write(ex);
                  }

              }, TaskCreationOptions.LongRunning);
        }

        bool CheckFile()
        {
            var fileName_serial = 0;
            this.InvMsg("aaflog_开始文件检查for循环");
            for (; fileName_serial < 10; fileName_serial++)
            {
                //Aaf20140221_1
                var fileName = "Aaf" + DateTime.Now.ToString("yyyyMMdd") + "_" + fileName_serial + ".log";
                FilePath = Path.Combine(this.RootPath, fileName);
                this.InvMsg("aaflog_当前文件" + FilePath);
                if (!File.Exists(FilePath))
                {
                    continue;
                }
                this.InvMsg("aaflog_当前文件存在");
                //判断当前文件是否最新文件
                var fileName2 = "Aaf" + DateTime.Now.ToString("yyyyMMdd") + "_" + (fileName_serial + 1) + ".log";
                var filePath2 = Path.Combine(this.RootPath, fileName2);
                if (!File.Exists(filePath2))
                {
                    if (fs != null)
                    {
                        fs.Close();
                        fs.Dispose();
                    }
                    this.InvMsg("aaflog_文件开始传输：" + FilePath);
                    //开新的线程，定时向服务器发送信息
                    fs = File.Open(this.FilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    return true;
                }
            }
            return false;
        }

        void TryFileTranRun()
        {
            var tryAgain = 0;
            do
            {
                try
                {
                    FileTranRun();
                    return;
                }
                catch (ThreadAbortException) { }
                catch (SocketException sex)
                {
                    this.InvMsg("aaflog_发送数据线程发送数据失败，" + sex.Message + "。5s后第" + tryAgain + "次重试。");
                    Thread.Sleep(5000);
                }
                catch (Exception ex)
                {
                    LogServices.LogService.Instance.Write(ex);
                }
                tryAgain++;
                if (tryAgain >= 5)
                {
                    this.HasConnected = false;
                    return;
                }
            } while (tryAgain < 5);
        }

        void FileTranRun()
        {
            this.InvMsg("aaflog_文件开始传输：开新的线程，定时向服务器发送信息");

            var emptyReadCount = 0;
            var data = new byte[102400];
            var readLen = 0;

            var command = new OnLineLogFileComm.Command();
            command.CommandType = OnLineLogFileComm.CommandType.SendFileName;
            command.Data = Path.GetFileName(fs.Name);
            this.InvMsg("aaflog_线程2发送数据：" + command.ToString());

            client.Send(command);
            var rData = client.Receive();
            dynamic lenObj = rData.GetObjData<dynamic>();
            this.InvMsg("aaflog_服务器文件，断点续传：" + rData.GetStringData());
            fs.Position = lenObj.len;

            do
            {
                readLen = fs.Read(data, 0, data.Length);
                if (readLen == 0)
                {
                    emptyReadCount++;
                    if (emptyReadCount > 5)
                    {
                        //对一个文件 5次读取到空。跳过文件.代表文件传输完成
                        this.FilePath = null;
                        emptyReadCount = 0;
                        fs.Close();
                        fs.Dispose();
                        command.CommandType = OnLineLogFileComm.CommandType.SendFileSuccess;
                        this.InvMsg("aaflog_线程2发送完成消息：" + command.ToString());

                        client.Send(command);
                        return;
                    }
                }
                else
                {
                    emptyReadCount = 0;
                    this.InvMsg("aaflog_线程2发送文件数据：" + readLen + "bit");
                    var sendData = new byte[readLen];
                    Array.Copy(data, 0, sendData, 0, readLen);
                    client.Send(sendData);
                }


                if (readLen < data.Length)
                {
                    this.InvMsg("aaflog_未读取到数据或数据传输完成线程2休眠10s：");
                    //已有的数据已读取完毕，等待1分钟。读取新产生的
                    Thread.Sleep(10000);//休眠1分钟
                }

            } while (true);
        }

        public override void Dispose()
        {

            if (this.fs != null)
            {
                this.fs.Close();
                this.fs.Dispose();
            }
            base.Dispose();
        }
    }
}
